package com.handydata.antifraud.common.task;

import com.handydata.antifraud.util.HttpUtil;
import com.handydata.antifraud.ws.EncryInfo;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.dmg.pmml.FieldName;
import org.dmg.pmml.PMML;
import org.jpmml.evaluator.*;
import org.jpmml.model.PMMLUtil;
import org.springframework.stereotype.Component;
import org.xml.sax.SAXException;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

@Slf4j
@Getter
@Setter
@Component
public class LoadPmmlRun implements Callable<PMML> {

    private EncryInfo encryInfo;

    private PMML pmml;

    /**
     * 处理模型文件
     * @return
     * @throws Exception
     */
    @Override
    public PMML call() throws Exception {
        pmml = new PMML();
        InputStream inputStream = this.getInputStream();
        try {
            log.info("SERVERURL={},FILEPATH={},FILE={}",this.getEncryInfo().getResporityServerUrl(), this.getEncryInfo().getResporityFilePath(), this.getEncryInfo().getResporityFile());
            inputStream = HttpUtil.getFileStream(this.getEncryInfo().getResporityServerUrl()+this.getEncryInfo().getResporityFilePath()+this.getEncryInfo().getResporityFile(),100000);
            if(inputStream == null){
                log.info("獲取InputStream流失敗:[{}]",inputStream);
                return null;
            }
            pmml = PMMLUtil.unmarshal(inputStream);
            return pmml;
        }catch (SAXException e) {
            log.error("解析模型文件出错SAXException1",e);
            e.printStackTrace();
        } catch (JAXBException e) {
            log.error("解析模型文件出错JAXBException2",e);
            e.printStackTrace();
        } catch (Exception e) {
            log.error("解析模型文件出错JAXBException3",e);
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public double predict(Map data) {
        ModelEvaluatorFactory modelEvaluatorFactory = ModelEvaluatorFactory.newInstance();
        Evaluator evaluator = modelEvaluatorFactory.newModelEvaluator(pmml);
        List<InputField> inputFields = evaluator.getInputFields();
        //过模型的原始特征，从画像中获取数据，作为模型输入
        Map<FieldName, FieldValue> arguments = new LinkedHashMap<FieldName, FieldValue>();
        for (InputField inputField : inputFields) {
            FieldName inputFieldName = inputField.getName();
            Object rawValue = data.get(inputFieldName.getValue());
            FieldValue inputFieldValue = inputField.prepare(rawValue);
            arguments.put(inputFieldName, inputFieldValue);
        }

        Map<FieldName, ?> results = evaluator.evaluate(arguments);
        List<TargetField> targetFields = evaluator.getTargetFields();
        TargetField targetField = targetFields.get(0);
        FieldName targetFieldName = targetField.getName();
        ProbabilityDistribution targetFieldValue= (ProbabilityDistribution)results.get(targetFieldName);
        return ((DoubleValue)targetFieldValue.getValues().get("1.0")).doubleValue();
    }

    public PMML getPmml() {
        return pmml;
    }

    public void setPmml(PMML pmml) {
        this.pmml = pmml;
    }


    public InputStream getInputStream(){
        return null;
    }

    public LoadPmmlRun(EncryInfo encryInfo) {
        this.encryInfo = encryInfo;
    }

    public LoadPmmlRun() {
    }
}
